package com.liuzhihang.doc.view.config;

import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.project.Project;
import com.intellij.util.xmlb.XmlSerializerUtil;
import com.liuzhihang.doc.view.constant.AnnotationConstant;
import com.liuzhihang.doc.view.constant.LombokConstant;
import com.liuzhihang.doc.view.constant.ValidationConstant;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.Set;

/**
 * 配置持久保存
 * <p>
 * <p>
 * See <a href="http://www.jetbrains.org/intellij/sdk/docs/basics/persisting_state_of_components.html">IntelliJ Platform SDK DevGuide</a>
 *
 * @author liuzhihang
 * @date 2020/2/27 19:02
 */
@State(name = "SettingsComponent", storages = {@Storage("DocViewSettings.xml")})
public class Settings implements PersistentStateComponent<Settings> {

    /**
     * 接口名字 fpc增加
     */
    private String nameTag = "DocView.Name";
    private Boolean nameUseSwagger3 = true;
    private Boolean nameUseSwagger = true;
    private Boolean nameUseCommentTag = true;
    private Boolean nameMethodComment = true;

    /**
     * 字段名称注解
     */
    private Set<String> fieldNameAnnotation = new HashSet<>() {{
        add("com.fasterxml.jackson.annotation.JsonProperty");
    }};
    /**
     * 字段名称取 JsonProperty 注解
     */
    private Boolean fieldNameJsonProperty = true;
    /**
     * 文档描述 fpc增加
     */
    private Boolean descUseSwagger3 = true;
    private Boolean descUseSwagger = true;

    /**
     * 包含类注解名称
     */
    private Set<String> containClassAnnotationName = new HashSet<String>() {{
        add(AnnotationConstant.CONTROLLER);
        add(AnnotationConstant.REST_CONTROLLER);
    }};

    /**
     * 包含方法注解名称
     */
    private Set<String> containMethodAnnotationName = new HashSet<String>() {{
        add(AnnotationConstant.GET_MAPPING);
        add(AnnotationConstant.POST_MAPPING);
        add(AnnotationConstant.PUT_MAPPING);
        add(AnnotationConstant.DELETE_MAPPING);
        add(AnnotationConstant.PATCH_MAPPING);
        add(AnnotationConstant.REQUEST_MAPPING);
    }};

    /**
     * 被注解的字段需要过滤掉
     */
    private Set<String> excludeFieldAnnotation = new HashSet<>() {{
        add("javax.annotation.Resource");
        add("org.springframework.beans.factory.annotation.Autowired");
        add("org.apache.dubbo.config.annotation.Reference");
        add("org.apache.dubbo.config.annotation.DubboReference");
    }};

    /**
     * 被注解的字段需要过滤掉
     */
    private Set<String> excludeClassPackage = new HashSet<>() {{
        add("com.baomidou.mybatisplus.extension.activerecord.Model");
    }};

    /**
     * 排除参数
     */
    private Set<String> excludeParamTypes = new HashSet<String>() {{
        add("HttpServletRequest");
        add("ServletRequest");
        add("HttpServletResponse");
        add("ServletResponse");
    }};

    /**
     * 排除字段
     */
    private Set<String> excludeParameterType = new HashSet<>() {{
        add("javax.servlet.ServletResponse");
        add("javax.servlet.ServletRequest");
    }};

    /**
     * 字段是否必填
     */
    private String required = "DocView.Required";

    /**
     * 是否使用注解
     */
    private Boolean requiredUseCommentTag = true;
    /**
     * 字段必填注解
     */
    private Set<String> requiredFieldAnnotation = new HashSet<>() {{
        add(ValidationConstant.NOT_BLANK);
        add(ValidationConstant.NOT_EMPTY);
        add(ValidationConstant.NOT_NULL);
        add(LombokConstant.NON_NULL);
    }};

    /**
     * 字段必填注解
     */
    private Set<String> fieldRequiredAnnotationName = new HashSet<String>() {{
        add(ValidationConstant.NOT_BLANK);
        add(ValidationConstant.NOT_EMPTY);
        add(ValidationConstant.NOT_NULL);
    }};

    /**
     * 排除字段
     */
    private Set<String> excludeFieldNames = new HashSet<String>() {{
        add("serialVersionUID");
    }};

    public static Settings getInstance(@NotNull Project project) {
        return ServiceManager.getService(project, Settings.class);
    }


    @Nullable
    @Override
    public Settings getState() {
        return this;
    }

    @Override
    public void loadState(@NotNull Settings state) {
        XmlSerializerUtil.copyBean(state, this);
    }

    public Set<String> getContainClassAnnotationName() {
        return containClassAnnotationName;
    }

    public void setContainClassAnnotationName(Set<String> containClassAnnotationName) {
        this.containClassAnnotationName = containClassAnnotationName;
    }

    public Set<String> getContainMethodAnnotationName() {
        return containMethodAnnotationName;
    }

    public void setContainMethodAnnotationName(Set<String> containMethodAnnotationName) {
        this.containMethodAnnotationName = containMethodAnnotationName;
    }

    public Set<String> getExcludeParamTypes() {
        return excludeParamTypes;
    }

    public void setExcludeParamTypes(Set<String> excludeParamTypes) {
        this.excludeParamTypes = excludeParamTypes;
    }

    public Set<String> getFieldRequiredAnnotationName() {
        return fieldRequiredAnnotationName;
    }

    public void setFieldRequiredAnnotationName(Set<String> fieldRequiredAnnotationName) {
        this.fieldRequiredAnnotationName = fieldRequiredAnnotationName;
    }

    public Set<String> getExcludeFieldNames() {
        return excludeFieldNames;
    }

    public void setExcludeFieldNames(Set<String> excludeFieldNames) {
        this.excludeFieldNames = excludeFieldNames;
    }

    public Boolean getDescUseSwagger3() {
        return descUseSwagger3;
    }

    public void setDescUseSwagger3(Boolean descUseSwagger3) {
        this.descUseSwagger3 = descUseSwagger3;
    }

    public Boolean getDescUseSwagger() {
        return descUseSwagger;
    }

    public void setDescUseSwagger(Boolean descUseSwagger) {
        this.descUseSwagger = descUseSwagger;
    }

    public String getNameTag() {
        return nameTag;
    }

    public void setNameTag(String nameTag) {
        this.nameTag = nameTag;
    }

    public Boolean getNameUseSwagger3() {
        return nameUseSwagger3;
    }

    public void setNameUseSwagger3(Boolean nameUseSwagger3) {
        this.nameUseSwagger3 = nameUseSwagger3;
    }

    public Boolean getNameUseSwagger() {
        return nameUseSwagger;
    }

    public void setNameUseSwagger(Boolean nameUseSwagger) {
        this.nameUseSwagger = nameUseSwagger;
    }

    public Boolean getNameUseCommentTag() {
        return nameUseCommentTag;
    }

    public void setNameUseCommentTag(Boolean nameUseCommentTag) {
        this.nameUseCommentTag = nameUseCommentTag;
    }

    public Boolean getNameMethodComment() {
        return nameMethodComment;
    }

    public void setNameMethodComment(Boolean nameMethodComment) {
        this.nameMethodComment = nameMethodComment;
    }

    public Set<String> getExcludeFieldAnnotation() {
        return excludeFieldAnnotation;
    }

    public void setExcludeFieldAnnotation(Set<String> excludeFieldAnnotation) {
        this.excludeFieldAnnotation = excludeFieldAnnotation;
    }

    public Set<String> getExcludeClassPackage() {
        return excludeClassPackage;
    }

    public void setExcludeClassPackage(Set<String> excludeClassPackage) {
        this.excludeClassPackage = excludeClassPackage;
    }

    public Set<String> getExcludeParameterType() {
        return excludeParameterType;
    }

    public void setExcludeParameterType(Set<String> excludeParameterType) {
        this.excludeParameterType = excludeParameterType;
    }

    public String getRequired() {
        return required;
    }

    public void setRequired(String required) {
        this.required = required;
    }

    public Boolean getRequiredUseCommentTag() {
        return requiredUseCommentTag;
    }

    public void setRequiredUseCommentTag(Boolean requiredUseCommentTag) {
        this.requiredUseCommentTag = requiredUseCommentTag;
    }

    public Set<String> getRequiredFieldAnnotation() {
        return requiredFieldAnnotation;
    }

    public void setRequiredFieldAnnotation(Set<String> requiredFieldAnnotation) {
        this.requiredFieldAnnotation = requiredFieldAnnotation;
    }

    public Set<String> getFieldNameAnnotation() {
        return fieldNameAnnotation;
    }

    public void setFieldNameAnnotation(Set<String> fieldNameAnnotation) {
        this.fieldNameAnnotation = fieldNameAnnotation;
    }

    public Boolean getFieldNameJsonProperty() {
        return fieldNameJsonProperty;
    }

    public void setFieldNameJsonProperty(Boolean fieldNameJsonProperty) {
        this.fieldNameJsonProperty = fieldNameJsonProperty;
    }
}
